# encoding: utf-8
__author__ = 'hansen'

import logging
import time

import simplejson

import CoinRPC
import SQLModel
from SQLModel import BLOCK, TRANSACTION, V_IN, V_OUT

HOST = '127.0.0.1'
PORT = 36345
USERNAME = 'dirkcoinrpc'
PASSWORD = '3WHExxNjSKPNfTBTqbLwc9ULnrcLDnvnjN9e82gs8Mcx'
dbsession = SQLModel.Session()
cnsession = CoinRPC.coinRPC(HOST, PORT, USERNAME, PASSWORD)

DELETE_ITEMS = 36           # 每次更新时删除的block数量

def delete_by_blk_height(begin_blk_height, end_blk_height):
    '''在数据库中删除blk_height为[begin_blk_height, end_blk_height)的有关内容'''
    for blk_height in range(begin_blk_height, end_blk_height):
        logging.debug(u'删除[blk_height=%s]的block的相关内容' % (blk_height,))
        for trade in dbsession.query(TRANSACTION).filter(TRANSACTION.blk_height == blk_height):
            for v_in in dbsession.query(V_IN).filter(V_IN.tx_hash == trade.tx_hash):
                logging.debug(u'[删除v_in] tx_hash=%s blk_height=%s' % (trade.tx_hash, blk_height))
                dbsession.delete(v_in)
            for v_out in dbsession.query(V_OUT).filter(V_OUT.tx_hash == trade.tx_hash):
                logging.debug(u'[删除v_out] tx_hash=%s blk_height=%s' % (trade.tx_hash, blk_height))
                dbsession.delete(v_out)
            logging.debug(u'[删除trade] blk_height=%s blk_height=%s' % (blk_height, blk_height))
            dbsession.delete(trade)
        for block in dbsession.query(BLOCK).filter(BLOCK.blk_height == blk_height):
            logging.debug(u'[删除block] blk_height=%s' % (blk_height))
            dbsession.delete(block)
        dbsession.commit()
        logging.debug(u'=====[blk_height=%s]的block的相关内容删除完毕=====' % (blk_height,))

def insert_by_blk_height(begin_blk_height, end_blk_height):
    '''在数据库中插入blk_height为[begin_blk_height, end_blk_height)的有关内容'''
    for blk_height in range(begin_blk_height, end_blk_height):
        blk_hash = cnsession.getblockhash(blk_height)
        logging.info('BLOCK:[%d]=>[%s]'%(blk_height, blk_hash))
        ####block
        blk_obj  = cnsession.getblock(blk_hash)
        block_db = SQLModel.BLOCK(
            blk_height=blk_height,
            blk_hash = blk_hash,
            blk_size = blk_obj['size'],
            blk_version = blk_obj['version'],
            blk_merkleroot = blk_obj['merkleroot'],
            blk_time = blk_obj['time'],
            blk_nonce = blk_obj['nonce'],
            blk_bits = blk_obj['bits'],
            blk_difficulty = blk_obj['difficulty']
        )
        dbsession.add(block_db)
        ####transaction
        for txitem in blk_obj['tx']:
            txobj = cnsession.getrawtransaction(txitem, 1)
            if txobj is None:
                logging.warn('TRANSACTION:[%s], Not found any transaction'%(txitem))
                break
            tx_db = SQLModel.TRANSACTION(
                tx_hash = txitem,
                tx_version=txobj['version'],
                tx_locktime=txobj['locktime'],
                tx_time = txobj['time'],
                blk_height = blk_height
            )
            dbsession.add(tx_db)
            #######v_in
            for vinitem in txobj['vin']:
                intx_hash = ''
                if vinitem.has_key('txid'):
                    intx_hash = vinitem['txid']
                vin_db = SQLModel.V_IN(
                    tx_hash = txitem,
                    intx_hash = intx_hash,
                    raw_msg = simplejson.dumps(vinitem)
                )
                dbsession.add(vin_db)
            #######v_out
            for voutitem in txobj['vout']:
                if len(voutitem['scriptPubKey'] ['addresses'])>1:
                    import pdb
                    pdb.set_trace()
                vout_db = SQLModel.V_OUT(
                    tx_hash = txitem,
                    amount=voutitem['value'],
                    address=voutitem['scriptPubKey'] ['addresses'] [0],
                    raw_msg=simplejson.dumps(voutitem)
                )
                dbsession.add(vout_db)
        if blk_height % 10 == 0:
            dbsession.commit()
    dbsession.commit()

def main(interval_time):
    while True:
        logging.info(u'****开始更新：%s' % (time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),) )
        # 获得当前数据库的block总数
        blk_indb_count = len(dbsession.query(BLOCK).all())
        # 删除
        delete_by_blk_height(blk_indb_count - DELETE_ITEMS, blk_indb_count)
        # 更新
        blk_count = cnsession.getblockcount()
        insert_by_blk_height(blk_indb_count - DELETE_ITEMS, blk_count)
        logging.info(u'****更新完毕：%s' % (time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),) )
        time.sleep(interval_time)

def initLog(log_path):
    import os,sys,copy,logging
    class MyConsoleHandler(logging.StreamHandler):
        def emit(self, record):
            myrecord = copy.copy(record)
            if os.name == 'nt':
                if isinstance(myrecord.msg, unicode):
                    myrecord.msg = myrecord.msg.encode('gbk')
                elif isinstance(myrecord.msg, str):
                    myrecord.msg = myrecord.msg.decode('utf-8').encode('gbk')
            logging.StreamHandler.emit(self, myrecord)
    logfile = os.path.join(log_path, os.path.basename(sys.argv[0]) + ".log")
    logger = logging.getLogger()
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
    ####handler
    hdlr = logging.FileHandler(logfile)
    chdlr = MyConsoleHandler()
    ####settings
    hdlr.setFormatter(formatter)
    chdlr.setFormatter(formatter)
    ######logger
    logger.addHandler(hdlr)
    logger.addHandler(chdlr)
    logger.setLevel(logging.NOTSET)
    #######requests
    req_logger = logging.getLogger('requests')
    req_logger.setLevel(logging.DEBUG)

if __name__ == '__main__':
    initLog('.')
    main(30)





